﻿using com.yoozoo.gta.Gameplay.PVE.Editor;
using DestroyIt;
using Gameplay.PVE;
using LogSystem;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.Rendering;
using XLua;
using Yoozoo.Core.Extensions.CSharp;
using Yoozoo.Gameplay.City;
using Yoozoo.Gameplay.Liberty;

namespace com.yoozoo.gta.Gameplay.PVE
{
    /// <summary>
    /// 测试场景物体-实际应用中可以根据需求增加或修改，只需实现ISceneObject接口即可
    /// </summary>
    [System.Serializable]
    [Obsolete("废弃，用SceneObjectInfo")]
    public class SceneObjectDisplay : ISceneObject
    {
        [SerializeField]
        private Bounds m_Bounds;
        [SerializeField]
        private string m_ResPath;
        [SerializeField]
        private Vector3 m_Position;
        public Vector3 Position => m_Position;
        
        [SerializeField]
        private Vector3 m_Rotation;
        [SerializeField]
        private Vector3 m_Size;
        [SerializeField]
        private int m_Index;
        [SerializeField] 
        private List<MeshRendererData> m_meshRendererDatas;
        [SerializeField]
        private bool m_isStatic = false;
        [SerializeField]
        private SceneObjType m_sceneType;
        private GameObject m_LoadedPrefab;

        private LodGroupContainer m_lodGroupContainer;
        
        /// <summary>
        /// 额外信息，用于不同模块
        /// 如：内城模块这里记录的为显示物体归属的房间ID
        /// </summary>
        [SerializeField]  
        private List<string> m_additionalInfo;
        
        private PrefabMeshRenderCache m_meshRenderCache;

        public SceneObjType SceneObjType
        {
            get { return m_sceneType; }
        }
        public bool IsStatic
        {
            get { return m_isStatic; }
        }
        public Bounds Bounds
        {
            get { return m_Bounds; }
        }

        public int Index
        {
            get
            {
                return m_Index;
            }
        }

        public GameObject LoadedPrefab => m_LoadedPrefab;
        
        public string GetAdditionInfo(int index)
        {
            if (m_additionalInfo.Count >= index+1)
            {
                return m_additionalInfo[index];
            }

            return null;
        }

        public void OnHide()
        {
            IsHide = true;
            if (m_LoadedPrefab)
            {
                // var rigidBody = m_LoadedPrefab.GetComponent<Rigidbody>();
                // if (rigidBody!=null)
                // {
                //     rigidBody.isKinematic = true;
                // }

                Destructible[] destructibles = m_LoadedPrefab.GetComponentsInChildren<Destructible>();
                foreach (var destructible in destructibles)
                {
                    destructible.enabled = false;
                    destructible.OnDelete();
                }
                
                ResObjectCacheManager.UnLoad(m_ResPath, m_LoadedPrefab);
                m_LoadedPrefab = null;
            }

            m_lodGroupContainer = null;
        }

        public void OnCrash()
        {
            if (m_LoadedPrefab)
            {
                var destructible = m_LoadedPrefab.GetComponent<Destructible>();
                if (destructible!=null)
                {
                    destructible.enabled = false;
                }
                m_LoadedPrefab.SetActive(false);
            }
        }
        
        public bool IsHide { get; set; }

        public bool OnShow(Transform parent,Action<GameObject> callBack = null)
        {
            IsHide = false;
            if (m_LoadedPrefab == null)
            {
                ResObjectCacheManager.Load(m_ResPath, (go) =>
                {
                    if (!IsHide)
                    {
                        m_LoadedPrefab = go;
                        m_LoadedPrefab.transform.SetParent(parent);

                        
                        if (LibertySceneManager.hasSceneRootOffset)
                        {
                            m_LoadedPrefab.transform.position = m_Position + LibertySceneManager.sceneRootOffset;
                        }
                        else
                        {
                            m_LoadedPrefab.transform.position = m_Position;
                        }
                        m_LoadedPrefab.transform.eulerAngles = m_Rotation;
                        m_LoadedPrefab.transform.localScale = m_Size;
                        
                        var rigidBody = m_LoadedPrefab.GetComponent<Rigidbody>();
                        if (rigidBody!=null)
                        {
                            // rigidBody.isKinematic = false;
                            rigidBody.velocity = Vector3.zero; // 重置线性速度
                            rigidBody.angularVelocity = Vector3.zero; // 重置角速度
                        }

                        var destructible = m_LoadedPrefab.GetComponent<Destructible>();
                        if (destructible!=null)
                        {
                            destructible.enabled = true;
                            destructible.CurrentHitPoints = destructible.TotalHitPoints;
                        }
                        
                        SetFarGameObjectMatrix[] setFarGameObjectMatrices = m_LoadedPrefab.GetComponentsInChildren<SetFarGameObjectMatrix>();
                        foreach (var setFarGameObjectMatrix in setFarGameObjectMatrices)
                        {
                            setFarGameObjectMatrix.SaveAllData(null);
                        }
                        
                        m_meshRenderCache = m_LoadedPrefab.GetComponent<PrefabMeshRenderCache>();
                        m_lodGroupContainer = m_LoadedPrefab.GetComponent<LodGroupContainer>();
                        
                        if (m_meshRenderCache)
                        {
                            for (int i = 0; i < m_meshRenderCache.MeshRenderers.Count; i++)
                            {
                                if (i > m_meshRendererDatas.Count - 1)
                                {
                                    Debug.LogError("此物体的MeshRender数据不匹配：" + m_LoadedPrefab.gameObject.name); 
                                    break;
                                }
                                MeshRenderer renderer = m_meshRenderCache.MeshRenderers[i];

                                if (renderer)
                                {
                                    renderer.lightmapIndex = m_meshRendererDatas[i].lightmapIndex;
                                    renderer.lightmapScaleOffset = m_meshRendererDatas[i].lightmapScaleOffset;
                                    
                                    if (renderer.reflectionProbeUsage != ReflectionProbeUsage.Off)
                                    {
                                        var result = new List<ReflectionProbeBlendInfo>();
                                        renderer.GetClosestReflectionProbes(result);
                                        if (result.IsNotEmpty())
                                        {
                                            // 目前只有银行场景需要反射探针，内城房间在LightMapApply中处理

                                            var info = result[0];
                                            var probe = info.probe;
                                            var probeTransform = probe.transform;

                                            var propertyBlock = new MaterialPropertyBlock();
                                            renderer.GetPropertyBlock(propertyBlock);
                                            var probePosition = probeTransform.position;
                                            var position = new Vector4
                                            {
                                                x = probePosition.x,
                                                y = probePosition.y,
                                                z = probePosition.z,
                                                w = info.weight
                                            };
                                            propertyBlock.SetVector(LightMapApply.PROBE_POSITION_PROPERTY_ID, position);
                                            propertyBlock.SetVector(LightMapApply.PROBE_BOXSIZE_PROPERTY_ID, probe.size);
                                            propertyBlock.SetVector(LightMapApply.PROBE_BOXOFFSET_PROPERTY_ID, probe.center);
                                            var rotation = Matrix4x4.TRS(probePosition,
                                                Quaternion.Inverse(probeTransform.rotation), Vector3.one);
                                            propertyBlock.SetMatrix(LightMapApply.PROBE_ROTATION_PROPERTY_ID, rotation);
                                            var baker = probe.GetComponent<HReflectionProbeBakeRotated>();
                                            propertyBlock.SetFloat(LightMapApply.PROBE_BOXSPHERE_RADIUS_PROPERTY_ID, baker?.sphereRadius ?? 0);
                                            renderer.SetPropertyBlock(propertyBlock);
                                        }

                                    }
                                }
                            }
                        }
                        
                        callBack?.Invoke(m_LoadedPrefab);
                    }
                    else
                    {
                        ResObjectCacheManager.UnLoad(m_ResPath, go);
                        m_LoadedPrefab = null;
                    }
                   
                });


                return true;
            }
            else
            {
                callBack?.Invoke(null);
            }
            return false;
        }
        
        public void ForceLOD(int index)
        {
            if (m_lodGroupContainer!=null && m_lodGroupContainer.lodGroups!=null)
            {
                foreach (var lodGroup in m_lodGroupContainer.lodGroups)
                {
                    if (lodGroup)
                    {
                        lodGroup.ForceLOD(index);
                    }
                }
            }    
        }
        
        public SceneObjectDisplay(Bounds bounds,Transform trans,int index, PrefabData prefabData,bool isStatic ,SceneObjType sceneObjType)
        {
            m_Bounds = bounds;
            m_Position = trans.position;
            m_Rotation = trans.eulerAngles;
            m_Size = trans.lossyScale;
            m_Index = index;
            m_ResPath = prefabData.resPath;
            m_meshRendererDatas = new List<MeshRendererData>();
            m_meshRendererDatas.AddRange(prefabData.MeshRendererDatas);
            m_isStatic = isStatic;
            m_sceneType = sceneObjType;
            m_additionalInfo = new List<string>(prefabData.additionalInfo);
        }

        public void AddLightmapIndices()
        {
            if (m_meshRenderCache)
            {
                foreach (var renderer in m_meshRenderCache.MeshRenderers)
                {
                    if (renderer)
                    {
                        LibertySceneManager.EnableLightmapIndex(renderer.lightmapIndex);
                    }
                }
            }
        }

        public void RemoveLightmapIndices()
        {
            if (m_meshRenderCache)
            {
                foreach (var renderer in m_meshRenderCache.MeshRenderers)
                {
                    if (renderer)
                    {
                        LibertySceneManager.DisableLightmapIndex(renderer.lightmapIndex);
                    }
                }
            }
        }

#if UNITY_EDITOR

        [BlackList]
        public void Generate(Transform parent, bool isStatic = false)
        {
            var o = AssetDatabase.LoadAssetAtPath<GameObject>(m_ResPath);
            if (o == null)
            {
                return;
            }
            var prefab = GameObject.Instantiate(o);
            var sdb = prefab.AddComponent<ScceneDataBind>();
            sdb.Index = m_Index;
            var objectBinder = prefab.GetComponent<SceneObjectBinder>();
            if (objectBinder && objectBinder.ObjectType == SceneObjType.Static)
            {
                isStatic = true;
            }
            
            if (isStatic)
            {
                sdb.ObjType = SceneObjType.Static;
            }

            prefab.transform.position = m_Position;
            prefab.transform.localScale = m_Size;
            prefab.transform.eulerAngles = m_Rotation;
            prefab.name = prefab.name;
            prefab.transform.SetParent(parent);

            
            PrefabMeshRenderCache meshRenderCache = prefab.GetComponent<PrefabMeshRenderCache>();
            if (meshRenderCache)
            {
                for (int i = 0; i < meshRenderCache.MeshRenderers.Count; i++)
                {
                    if (i > m_meshRendererDatas.Count - 1)
                    {
                        break;
                    }
                    MeshRenderer renderer = meshRenderCache.MeshRenderers[i];
                    renderer.lightmapIndex = m_meshRendererDatas[i].lightmapIndex;
                    renderer.lightmapScaleOffset = m_meshRendererDatas[i].lightmapScaleOffset;
                }
            }

            LightMapApply lightMapApply = prefab.AddComponent<LightMapApply>();
            lightMapApply.MeshRenderCache = meshRenderCache;
            lightMapApply.MeshRendererDatas = new List<MeshRendererData>();
            lightMapApply.MeshRendererDatas.AddRange(m_meshRendererDatas);
        }

        [BlackList]
        public void Check(int index, bool isStatic, SceneObjType sceneObjType, Dictionary<string, List<SceneObjectDisplay>> map)
        {
            string prefabName = Path.GetFileNameWithoutExtension(m_ResPath);

            // 少量物件 10%，会旋转X，Z轴
            //if (m_Rotation.x != 0)
            //    Debug.Log(LogModule.City, $"[{prefabName}][{index}].rotation.x = {m_Rotation.x}");

            //if (m_Rotation.z != 0)
            //    Debug.Log(LogModule.City, $"[{prefabName}][{index}].rotation.z = {m_Rotation.z}");

            // 少量物件会不整体缩放
            //if (Math.Abs(m_Size.x - m_Size.y) > TOLERANCE || Math.Abs(m_Size.x - m_Size.z) > TOLERANCE ||
            //    Math.Abs(m_Size.y - m_Size.z) > TOLERANCE)
            //    Debug.Log(LogModule.City, $"[{prefabName}][{index}].size = {m_Size}");

            for (var j = 0; j < m_meshRendererDatas.Count; j++)
            {
                var data = m_meshRendererDatas[j];
                if (data.lightmapIndex >= 0)
                    Debug.Log(LogModule.City, $"[{prefabName}][{index}].meshRendererDatas[{j}].lightMapIndex = {data.lightmapIndex}");
            }

            if(IsStatic != isStatic)
                Debug.Log(LogModule.City, $"[{prefabName}][{index}].IsStatic = {IsStatic}");

            if(m_sceneType != sceneObjType)
                Debug.Log(LogModule.City, $"[{prefabName}][{index}].SceneType = {m_sceneType}");

            for (var j = 0; j < m_additionalInfo.Count; j++)
            {
                var info = m_additionalInfo[j];
                if (!string.IsNullOrEmpty(info))
                    Debug.Log(LogModule.City, $"[{prefabName}][{index}].additionalInfo[{j}] = {info}");
            }

            if (map.TryGetValue(m_ResPath, out var list))
            {
                var firstItem = list[0];
                if(firstItem.m_Bounds.extents != m_Bounds.extents)
                    Debug.Log(LogModule.City, $"[{prefabName}][{index}].m_Bounds.extents = {m_Bounds.extents} != {firstItem.m_Bounds.extents}");
                else 
                    list.Add(this);
            }
            else
            {
                list = new List<SceneObjectDisplay>();
                list.Add(this);
            }
        }

        private const float TOLERANCE = 0.0001f;
#endif

    }
}
